<script setup lang="ts">
import { ref, onMounted, watch, nextTick, onBeforeUnmount } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const tocItems = ref<Array<{ id: string; text: string; level: number }>>([])
const isMarkdownPage = ref(false)
const activeHeadingId = ref('')

// 生成目录
const generateToc = () => {
  // 检查是否为markdown页面
  isMarkdownPage.value = route.path.startsWith('/docs/') && route.path !== '/docs/'

  if (!isMarkdownPage.value) {
    tocItems.value = []
    return
  }

  // 使用nextTick等待DOM更新完成
  nextTick(() => {
    const markdownBody = document.querySelector('.markdown-body')
    if (!markdownBody) return

    const headings = markdownBody.querySelectorAll('h1, h2, h3, h4, h5, h6')
    const items: Array<{ id: string; text: string; level: number }> = []

    headings.forEach((heading) => {
      const text = heading.textContent || ''
      const level = parseInt(heading.tagName.substring(1))

      // 生成ID - 支持中文标题
      let id = text
        .trim() // 移除首尾空格
        .replace(/\s+/g, '-') // 空格替换为连字符
        .replace(/-+/g, '-') // 多个连字符替换为一个

      // 如果ID为空或只包含特殊字符，则使用标题的Unicode编码
      if (!id || /^[-]+$/.test(id)) {
        id = 'heading-' + encodeURIComponent(text).replace(/%/g, '')
      }

      // 确保ID唯一
      let uniqueId = id
      let counter = 1
      while (document.getElementById(uniqueId)) {
        uniqueId = `${id}-${counter}`
        counter++
      }

      // 设置ID
      heading.id = uniqueId

      items.push({
        id: uniqueId,
        text,
        level,
      })
    })

    tocItems.value = items
    // 初始化高亮当前标题
    updateActiveHeading()
  })
}

// 更新当前活动标题
const updateActiveHeading = () => {
  const headings = document.querySelectorAll(
    '.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6',
  )
  const navbarHeight = 70
  const scrollPosition = window.scrollY + navbarHeight + 20 // 添加20px的偏移量

  for (let i = headings.length - 1; i >= 0; i--) {
    const heading = headings[i] as HTMLElement
    const offsetTop = heading.offsetTop

    if (offsetTop <= scrollPosition) {
      activeHeadingId.value = heading.id
      return
    }
  }

  // 如果没有匹配的标题，则使用第一个标题
  if (headings.length > 0) {
    activeHeadingId.value = (headings[0] as HTMLElement).id
  }
}

// 监听滚动事件，更新当前活动标题
const handleScroll = () => {
  updateActiveHeading()
}

// 滚动到指定标题
const scrollToHeading = (id: string, event: Event) => {
  event.preventDefault()
  const element = document.getElementById(id)
  if (element) {
    // 计算导航栏高度，以便滚动时正确偏移
    const navbarHeight = 70
    const elementPosition = element.getBoundingClientRect().top
    const offsetPosition = elementPosition + window.pageYOffset - navbarHeight

    // 使用scrollTo而不是router.replace，避免触发路由的滚动行为
    window.scrollTo({
      top: offsetPosition,
      behavior: 'smooth',
    })

    // 更新URL哈希，但不触发路由导航
    const currentRoute = route.fullPath
    const hashIndex = currentRoute.indexOf('#')
    const basePath = hashIndex !== -1 ? currentRoute.substring(0, hashIndex) : currentRoute

    // 只有当哈希值不同时才更新
    if (route.hash !== `#${id}`) {
      // 使用history.replaceState而不是router.replace，避免触发路由的滚动行为
      history.replaceState(null, '', `${basePath}#${id}`)
    }

    // 触发事件关闭目录抽屉
    emit('close-drawer')
  }
}

// 定义 emit 事件
const emit = defineEmits(['close-drawer'])

// 监听路由变化
watch(
  () => route.path,
  () => {
    generateToc()
  },
)

onMounted(() => {
  generateToc()
  // 添加滚动事件监听
  window.addEventListener('scroll', handleScroll)
})

// 组件卸载时移除事件监听
onBeforeUnmount(() => {
  window.removeEventListener('scroll', handleScroll)
})
</script>

<template>
  <div class="toc-container" v-if="isMarkdownPage && tocItems.length > 0">
    <div class="toc-header">
      <h3>目录</h3>
    </div>
    <div class="toc-content">
      <ul>
        <li
          v-for="item in tocItems"
          :key="item.id"
          :class="['toc-level-' + item.level, { active: activeHeadingId === item.id }]"
          @click="scrollToHeading(item.id, $event)"
        >
          <a href="javascript:void(0)" @click.prevent>{{ item.text }}</a>
        </li>
      </ul>
    </div>
  </div>
</template>

<style scoped>
.toc-container {
  position: static;
  top: auto;
  right: auto;
  height: 100%;
  width: 100%;
  z-index: auto;
  background-color: transparent;
  padding: 0;
  overflow-y: auto;
  border-left: none;
}

/* 隐藏滚动条 - Webkit浏览器 (Chrome, Safari) */
.toc-container::-webkit-scrollbar {
  display: none;
}

.toc-header {
  font-family: 'Microsoft YaHei', 'SimHei', sans-serif;
  font-size: 1.1rem;
  font-weight: 600;
  padding: 8px 10px;
  border-radius: 4px;
  margin-bottom: 8px;
  color: #2c3e50;
  letter-spacing: 0.5px;
}

.toc-header h3 {
  margin: 0;
  font-size: 1.2rem;
  font-weight: 900;
  color: #2c3e50;
}

.toc-content {
  width: 100%;
  padding-left: 10px;
}

.toc-content ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.toc-content li {
  padding: 6px 10px;
  border-radius: 4px;
  margin-bottom: 8px;
  color: #2c3e50;
  cursor: pointer;
}

.toc-content li:hover {
  color: #3a8ee6;
}

.toc-content a {
  color: #2c3e50;
  text-decoration: none;
  font-size: 0.9rem;
  display: block;
  font-family: 'Microsoft YaHei', 'SimSun', sans-serif;
  letter-spacing: 0.3px;
  line-height: 1.4;
}

.toc-content li:hover a {
  color: #3a8ee6;
}

.toc-level-1 {
  font-weight: 700;
  font-size: 1rem;
}

.toc-level-2 {
  margin-left: 15px;
  font-weight: 600;
}

.toc-level-3 {
  margin-left: 30px;
  font-weight: 500;
}

.toc-level-4 {
  margin-left: 45px;
  font-weight: 400;
}

.toc-level-5 {
  margin-left: 60px;
  font-weight: 400;
}

.toc-level-6 {
  margin-left: 75px;
  font-weight: 300;
}

/* 活动标题高亮样式 */
.toc-content li.active {
  border-left: 2px solid #3a8ee6;
  padding-left: 8px;
}

.toc-content li.active a {
  color: #3a8ee6;
}
</style>
